home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- newswatcher.c
-
- This module contains the main entry point of the program and the main
- event loop.
-
- Copyright © 1994-1995, Northwestern University.
-
- ----------------------------------------------------------------------------*/
-
-
-
- #include <string.h>
- #include <stdio.h>
- #include <ctype.h>
-
- #include <CodeFragments.h>
-
- #include "glob.h"
- #include "newswatcher.h"
- #include "about.h"
- #include "newsrc.h"
- #include "full.h"
- #include "prefsdlog.h"
- #include "menus.h"
- #include "news.h"
- #include "prefs.h"
- #include "print.h"
- #include "log.h"
- #include "net.h"
- #include "nntp.h"
- #include "message.h"
- #include "wind.h"
- #include "dialog.h"
- #include "aevt.h"
- #include "group.h"
- #include "subject.h"
- #include "article.h"
- #include "status.h"
- #include "text.h"
- #include "memutil.h"
- #include "spin.h"
- #include "windutil.h"
- #include "fileutil.h"
- #include "cache.h"
- #include "strutil.h"
- #include "resutil.h"
- #include "open.h"
- #include "teutil.h"
- #include "dummy.h"
- #include "sfutil.h"
- #include "drawutil.h"
- #include "ldef.h"
- #include "url.h"
- #include "subscribe.h"
- #include "ic.h"
- #include "genutil.h"
- #include "help.h"
-
-
-
- /*#define testingOT 1*/
- #define OTTestHost "cash.acns.nwu.edu"
- #define OTTestUser "jln"
- #define OTTestPswd "xxx"
- #define OTTestPath "ottest"
- #define OTTestName "\pottest"
- #define OTDelay 0
-
-
-
- #define kNeedSystem7AlertID 500 /* need System 7.0 or later alert id */
- #define kTPrefRecSize 7960 /* preferences record size */
-
- #define kErrorDuringQuitDlg 155
- #define kErrorDuringQuitDlgQuitItem 1
-
- #define kWaitForDNRDlg 154 /* wait for DNR dialog */
- #define kRetryConnectID 166 /* retry news server connect dialog */
-
-
- static WindowPtr gMouseDownWindow = nil; /* pointer to window in which mouse
- down happened */
-
-
-
- /*----------------------------------------------------------------------------
- DoClose
-
- Close a window.
-
- Entry: wind = pointer to window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr DoClose (WindowPtr wind)
- {
- TWindowKind kind;
- GrafPtr port;
- OSErr err = noErr;
-
- kind = GetMyWindowKind(wind);
- if (kind != kNotOurWind) {
- GetPort(&port);
- SetPort(wind);
- err = (*gDispatch[kind].close)(wind);
- SetPort(port);
- }
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoZoom
-
- Zoom a window.
-
- Entry: wind = pointer to window.
- zoomDir = zoom direction = inZoomIn or inZoomOut.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
-
- OSErr DoZoom (WindowPtr wind, short zoomDir)
- {
- TWindowKind kind;
- GrafPtr port;
- OSErr err = noErr;
-
- kind = GetMyWindowKind(wind);
- if (kind != kNotOurWind) {
- GetPort(&port);
- SetPort(wind);
- err = (*gDispatch[kind].zoom)(wind, zoomDir);
- SetPort(port);
- }
-
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoCommand
-
- Do a command.
-
- Entry: mResult = 16/menu, 16/item.
- modifiers = modifiers field from event record.
-
- Exit: function result = error code.
-
- Commands which act on the frontmost window are dispatched to the
- proper window handling module. Other commands are handled directly,
- without invoking a window handling module.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoCommand (long mResult, short modifiers)
- {
- short menu, item;
- WindowPtr wind;
- TWindowKind kind;
- GrafPtr port;
- Boolean commandHandled;
- Str255 daName;
- OSErr err = noErr;
-
- menu = HiWord(mResult);
- item = LoWord(mResult);
-
- wind = FrontWindow();
- kind = GetMyWindowKind(wind);
-
- commandHandled = true;
-
- switch (menu) {
-
- case kAppleMenu:
-
- switch (item) {
- case kAboutNewsWatcherItem:
- err = DoAboutNewsWatcher();
- break;
- default:
- GetPort(&port);
- SetCursor(&qd.arrow);
- GetMenuItemText(GetMenuHandle(kAppleMenu), item, daName);
- OpenDeskAcc(daName);
- SetPort(port);
- break;
- }
- break;
-
- case kFileMenu:
-
- switch (item) {
- case kNewGroupWindowItem:
- err = DoNewGroupWindow();
- break;
- case kOpenItem:
- err = DoOpen();
- break;
- case kCloseItem:
- err = DoClose(wind);
- break;
- case kPageSetupItem:
- err = DoPageSetup();
- break;
- case kPreferencesItem:
- err = DoPreferences();
- break;
- case kQuitItem:
- gDone = true;
- break;
- default:
- commandHandled = false;
- break;
- }
- break;
-
- case kEditMenu:
-
- commandHandled = false;
- break;
-
- case kNewsMenu:
-
- switch (item) {
- case kNewMessageItem:
- err = DoNewMessage();
- break;
- default:
- commandHandled = false;
- break;
- }
- break;
-
- case kSpecialMenu:
-
- switch (item) {
- case kGetGroupListFromHostItem:
- err = DoGetGroupListFromHost();
- break;
- case kGetServerInfoItem:
- err = DoGetServerInfo();
- break;
- case kOpenURLItem:
- err = DoOpenURL(wind);
- break;
- case kCheckForNewGroupsItem:
- err = DoCheckForNewGroups();
- break;
- case kCheckForDeletedGroupsItem:
- err = DoCheckForDeletedGroups();
- break;
- case kRebuildFullGroupListItem:
- err = DoRebuildFullGroupList();
- break;
- default:
- commandHandled = false;
- break;
- }
- break;
-
- case kWindMenu:
-
- switch (item) {
- case kCycleWindowsItem:
- DoCycleWindows(wind);
- break;
- case kZoomWindowItem:
- err = DoZoomWindow(wind);
- break;
- case kShowHideFullGroupListItem:
- err = DoShowHideFullGroupList();
- break;
- default:
- SelectWindMenu(item);
- break;
- }
- break;
-
- case kHMHelpMenuID:
-
- err = DoHelpMenuCommand(item);
- break;
- }
-
- if (!commandHandled && kind != kNotOurWind) {
- GetPort(&port);
- SetPort(wind);
- err = (*gDispatch[kind].command)(wind, menu, item, modifiers);
- SetPort(port);
- }
-
- HiliteMenu(0);
-
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Draggable
-
- Determine whether a mouse down event is in a draggable object in a
- window.
-
- Entry: wind = pointer to window.
- where = location of mouse down event, in local coordinates.
- modifiers = modifiers field from event record.
-
- Exit: function result = true if object is draggable.
- ----------------------------------------------------------------------------*/
-
- static Boolean Draggable (WindowPtr wind, Point where, short modifiers)
- {
- GrafPtr port;
- TWindowKind kind;
- Boolean result = false;
-
- if (!gHaveDragMgr) return false;
- kind = GetMyWindowKind(wind);
- if (kind != kNotOurWind) {
- GetPort(&port);
- SetPort(wind);
- result = (*gDispatch[kind].draggable)(wind, where, modifiers);
- SetPort(port);
- }
-
- return result;
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleGrow
-
- Handle a mouse down event in the grow box of a window.
-
- Entry: wind = pointer to window.
- where = location of mouse down event, in global coordinates.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr HandleGrow (WindowPtr wind, Point where)
- {
- GrafPtr port;
- TWindowKind kind;
- OSErr err = noErr;
-
- kind = GetMyWindowKind(wind);
- if (kind != kNotOurWind) {
- GetPort(&port);
- SetPort(wind);
- err = (*gDispatch[kind].grow)(wind, where);
- SetPort(port);
- }
-
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleDrag
-
- Handle a window drag operation.
-
- Entry: wind = pointer to window.
- where = location of mouse down event, in global coordinates.
- ----------------------------------------------------------------------------*/
-
- static void HandleDrag (WindowPtr wind, Point where)
- {
- Rect r;
- GrafPtr port;
- Point oldTopLeft = {0, 0};
- Point newTopLeft = {0, 0};
- TWindow **info;
-
- GetPort(&port);
- SetPort(wind);
- LocalToGlobal(&oldTopLeft);
- r = gDesktopExtent;
- InsetRect(&r, 4, 4);
- DragWindow(wind, where, &r);
- LocalToGlobal(&newTopLeft);
- if (oldTopLeft.h != newTopLeft.h || oldTopLeft.v != newTopLeft.v) {
- if (GetMyWindowKind(wind) != kNotOurWind) {
- info = (TWindow**)GetWRefCon(wind);
- (**info).windPosValid = true;
- (**info).movedSinceLastSave = true;
- }
- }
- SetPort(port);
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleActivate
-
- Activate or deactivate a window.
-
- Entry: wind = pointer to window.
- act = true to activate, false to deactivate.
- ----------------------------------------------------------------------------*/
-
- void HandleActivate (WindowPtr wind, Boolean act)
- {
- GrafPtr port;
- TWindowKind kind;
-
- kind = GetMyWindowKind(wind);
- if (kind != kNotOurWind) {
- GetPort(&port);
- SetPort(wind);
- (*gDispatch[kind].activate)(wind, act);
- SetPort(port);
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleUpdate
-
- Update a window.
-
- Entry: wind = pointer to window.
- ----------------------------------------------------------------------------*/
-
- void HandleUpdate (WindowPtr wind)
- {
- GrafPtr port;
- TWindowKind kind;
-
- kind = GetMyWindowKind(wind);
- if (kind != kNotOurWind) {
- GetPort(&port);
- SetPort(wind);
- BeginUpdate(wind);
- EraseRect(&wind->portRect);
- (*gDispatch[kind].update)(wind);
- EndUpdate(wind);
- SetPort(port);
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleMouseDown
-
- Handle mouse down events.
-
- Entry: ev = pointer to event record.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr HandleMouseDown (EventRecord *ev)
- {
- WindowPtr front, wind;
- TWindowKind frontKind, kind;
- short part;
- GrafPtr port;
- Point where;
- short modifiers;
- OSErr err = noErr;
-
- front = FrontWindow();
- frontKind = GetMyWindowKind(front);
- part = FindWindow(ev->where, &wind);
- kind = GetMyWindowKind(wind);
- where = ev->where;
- modifiers = ev->modifiers;
-
- if (gLongOperation && part != inMenuBar && frontKind != kStatus) return noErr;
-
- switch (part) {
-
- case inMenuBar:
-
- if (gLongOperation) SetMenusTo(kAppleOnlyAboutDisabled, 0, 0, 0, 0, 0);
- err = DoCommand(MenuSelect(where), modifiers);
- break;
-
- case inSysWindow:
-
- SystemClick(ev, wind);
- break;
-
- case inDrag:
-
- if (front != wind && (frontKind == kStatus || frontKind == kDialog)) {
- SysBeep(0);
- } else {
- HandleDrag(wind, where);
- }
- break;
-
- case inGrow:
-
- err = HandleGrow(wind, where);
- break;
-
- case inGoAway:
-
- if (TrackGoAway(wind, where)) err = DoClose(wind);
- break;
-
- case inZoomIn:
- case inZoomOut:
-
- if (TrackBox(wind, where, part)) err = DoZoom(wind, part);
- break;
-
- case inContent:
-
- GetPort(&port);
- SetPort(wind);
- GlobalToLocal(&where);
- if (front == wind) {
- if (kind != kNotOurWind)
- err = (*gDispatch[kind].mouse)(wind, where, modifiers);
- } else {
- if (frontKind != kStatus && frontKind != kDialog) {
- if (Draggable(wind, where, modifiers)) {
- err = (*gDispatch[kind].mouse)(wind, where, modifiers);
- gMouseDownWindow = wind;
- } else {
- SelectWindow(wind);
- }
- } else {
- SysBeep(0);
- }
- }
- SetPort(port);
- break;
-
- }
-
- return err;
-
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleMouseUp
-
- Handle mouse up events.
-
- Entry: ev = pointer to event record.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr HandleMouseUp (EventRecord *ev)
- {
- WindowPtr wind = nil;
- short part;
- TWindowKind frontKind;
-
- if (gMouseDownWindow == nil) return noErr;
- frontKind = GetMyWindowKind(FrontWindow());
- if (frontKind == kDialog || frontKind == kStatus) goto exit;
- part = FindWindow(ev->where, &wind);
- if (wind == gMouseDownWindow) SelectWindow(wind);
-
- exit:
-
- gMouseDownWindow = nil;
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleKey
-
- Handle key down events.
-
- Entry: ev = pointer to event record.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr HandleKey (EventRecord *ev)
- {
- unsigned char theChar;
- unsigned char theKey;
- short modifiers;
- long menuCmd;
- WindowPtr wind;
- TWindowKind kind;
- GrafPtr port;
- OSErr err = noErr;
-
- wind = FrontWindow();
- kind = GetMyWindowKind(wind);
- theChar = ev->message & charCodeMask;
- theKey = (ev->message & keyCodeMask) >> 8;
- modifiers = ev->modifiers;
-
- /* Map F1,2,3,4 to Undo, Cut, Copy, Paste */
-
- if (theKey == 0x7A) {
- modifiers = cmdKey;
- theChar = 'Z';
- } else if (theKey == 0x78) {
- modifiers = cmdKey;
- theChar = 'X';
- } else if (theKey == 0x63) {
- modifiers = cmdKey;
- theChar = 'C';
- } else if (theKey == 0x76) {
- modifiers = cmdKey;
- theChar = 'V';
- }
-
- if (gLongOperation && kind != kStatus) {
- if (theKey == escapeKeyCode || (modifiers & cmdKey) != 0 && theChar == '.')
- gCancel = true;
- return noErr;
- }
-
- #ifdef kDevelopmentVersion
- if (!gLongOperation && (modifiers & cmdKey) != 0 && (modifiers & optionKey) != 0) {
- if (theKey == 29) { /* cmd-opt-0 */
- DebugStr("\pYou asked for it!");
- return noErr;
- }
- if (theKey == 20) { /* cmd-opt-3 */
- return DisplayArticleCache();
- }
- if (theKey == 21) { /* cmd-opt-4 */
- FlushArticleCache();
- return noErr;
- }
- if (theKey == 23) { /* cmd-opt-5 */
- CompactArticleCache();
- return noErr;
- }
- }
- #endif
-
- if (!gLongOperation && (modifiers & cmdKey) != 0) {
- if ((modifiers & optionKey) != 0) {
- if (theKey == 40) theChar = 'K';
- if (theKey == 37) theChar = 'L';
- if (theKey == 15) theChar = 'R';
- if (theKey == 01) theChar = 'S';
- if (theKey == 11) theChar = 'B';
- }
- menuCmd = MenuKey(theChar);
- if (HiWord(menuCmd) != 0) return DoCommand(menuCmd, modifiers);
- }
-
- if (!gLongOperation) {
- if (theChar == helpKey ||
- (modifiers & cmdKey) != 0 && (theChar == '?' || theChar == '/'))
- {
- err = OpenFirstHelpTopicWindow();
- return err;
- }
- }
-
- if (kind != kNotOurWind) {
- if (!gLongOperation) ObscureCursor();
- GetPort(&port);
- SetPort(wind);
- err = (*gDispatch[kind].key)(wind, theChar, theKey, modifiers);
- SetPort(port);
- }
-
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleOSEvt
-
- Handle OS events (suspend and resume).
-
- Entry: ev = pointer to event record.
- ----------------------------------------------------------------------------*/
-
- static void HandleOSEvt (EventRecord *ev)
- {
- WindowPtr wind;
- Boolean resume;
-
- if (((ev->message >> 24) & 0xff) != suspendResumeMessage) return;
- SetCursor(&qd.arrow);
- wind = FrontWindow();
- resume = (ev->message & 1) == resumeFlag;
- gInBackground = !resume;
- HandleActivate(wind, resume);
- if (resume) AdjustWindowTitlesOnResume();
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleIdle
-
- Handle idle tasks.
-
- Exit: cursorRgn = cursor region for WaitNextEvent mouse moved events.
- ----------------------------------------------------------------------------*/
-
- void HandleIdle (RgnHandle cursorRgn)
- {
- WindowPtr wind;
- TWindowKind kind;
- GrafPtr port;
- unsigned long windEnabled;
- Point where;
-
- NetIdle();
- NntpIdle();
-
- RebuildWindowsMenu();
-
- wind = FrontWindow();
- kind = GetMyWindowKind(wind);
-
- SetRectRgn(cursorRgn, -0x7fff, -0x7fff, 0x7fff, 0x7fff);
-
- if (kind == kNotOurWind) {
- SetCursor(&qd.arrow);
- if (IsDAWindow(wind)) {
- SetMenusTo(kAppleAllEnabled, kDAFileEnabled, kDAEditEnabled,
- kDANewsEnabled, kDASpecialEnabled,kDAWindEnabled);
- } else if (!gStartupOK) {
- windEnabled = wind == nil ? 0 : kStartupBadWindEnabled;
- SetMenusTo(kAppleAllEnabled, kStartupBadFileEnabled, kStartupBadEditEnabled,
- kStartupBadNewsEnabled, kStartupBadSpecialEnabled, windEnabled);
- } else if (wind == nil) {
- SetMenusTo(kAppleAllEnabled, kNoneFileEnabled, kNoneEditEnabled,
- kNoneNewsEnabled, kNoneSpecialEnabled, kNoneWindEnabled);
- }
- } else {
- GetPort(&port);
- SetPort(wind);
- (*gDispatch[kind].idle)(wind, cursorRgn);
- if (!gInBackground && HMGetBalloons() && !HMIsBalloon()) {
- GetMouse(&where);
- if (PtInRect(where, &wind->portRect)) (*gDispatch[kind].help)(wind, where);
- }
- SetPort(port);
- }
- AdjustCycleWindowsCommand();
- AdjustMenuHelpBalloons(false);
- AdjustHelpMenu();
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleEvent
-
- Handle an event.
-
- Entry: ev = pointer to event.
- ----------------------------------------------------------------------------*/
-
- void HandleEvent (EventRecord *ev)
- {
- WindowPtr front;
- WindowPeek peek;
- Boolean isDialog = false;
- Point thisPoint;
- OSErr err = noErr;
-
- front = FrontWindow();
- if (front != nil) {
- peek = (WindowPeek)front;
- if (peek->windowKind == dialogKind) isDialog = true;
- }
-
- if (isDialog) gLongOperation = false;
-
- switch (ev->what) {
- case activateEvt:
- HandleActivate((WindowPtr)ev->message, (ev->modifiers & activeFlag) != 0);
- break;
- case updateEvt:
- HandleUpdate((WindowPtr)ev->message);
- break;
- case mouseDown:
- err = HandleMouseDown(ev);
- break;
- case mouseUp:
- err = HandleMouseUp(ev);
- break;
- case keyDown:
- case autoKey:
- err = HandleKey(ev);
- break;
- case osEvt:
- HandleOSEvt(ev);
- break;
- case kHighLevelEvent:
- MyAEProcessAppleEvent(ev);
- gLongOperation = false;
- break;
- case diskEvt:
- if ((ev->message & 0xffff0000) != 0) {
- DILoad();
- SetPt(&thisPoint, 120, 120);
- DIBadMount(thisPoint, ev->message);
- DIUnload();
- }
- break;
- }
-
- ReportSystemError(err);
- }
-
-
-
- /*----------------------------------------------------------------------------
- Quit
-
- Close windows prior to quitting.
-
- Exit: function result = true if OK to quit, false if error or
- canceled by user.
- ----------------------------------------------------------------------------*/
-
- static Boolean Quit (void)
- {
- WindowPtr wind;
- Str255 fullGroupWindowFont;
- OSErr err = noErr;
- Boolean fullGroupListWasVisible;
- DialogPtr dlg;
- short item;
-
- fullGroupListWasVisible = gFullGroupWindow != nil &&
- ((WindowPeek)gFullGroupWindow)->visible;
-
- while (true) {
- wind = FrontWindow();
- while (wind != nil && GetMyWindowKind(wind) == kNotOurWind)
- wind = (WindowPtr)((WindowPeek)wind)->nextWindow;
- if (wind == nil) break;
- err = DoClose(wind);
- if (err == userCanceledErr) goto exit1;
- if (err != noErr) {
- ReportSystemError(err);
- err = MyGetNewDialog(kErrorDuringQuitDlg, kErrorDuringQuitDlgQuitItem, cancel, &dlg);
- if (err != noErr) goto exit;
- SysBeep(0);
- MyModalDialog(dlg, gDialogFilterUPP, &item);
- err = DoClose(dlg);
- if (err != noErr) goto exit;
- if (item == kErrorDuringQuitDlgQuitItem) {
- break;
- } else {
- goto exit1;
- }
- }
- }
-
- if (gFullGroupWindow != nil) {
- MyICReadSharedPrefs(kICListFont);
- gPrefs.fullGroupListVisible = fullGroupListWasVisible;
- GetFontName(gFullGroupWindow->txFont, fullGroupWindowFont);
- if (gPrefs.listSize != gFullGroupWindow->txSize ||
- !EqualString(gPrefs.listFont, fullGroupWindowFont, false, true))
- gPrefs.maxGroupNameWidth = 0;
- }
-
- return true;
-
- exit:
-
- ReportSystemError(err);
-
- exit1:
-
- if (gFullGroupWindow != nil && fullGroupListWasVisible &&
- !((WindowPeek)gFullGroupWindow)->visible)
- {
- MyShowWindow(gFullGroupWindow);
- SetWindowsMenuShowHideFullGroupList(false);
- }
- return false;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MainEvent
-
- Main event loop.
- ----------------------------------------------------------------------------*/
-
- static void MainEvent (void)
- {
- EventRecord ev;
- RgnHandle cursorRgn, rgn;
- Boolean gotEvt;
- WindowPtr wind;
- Boolean memOK;
- static Boolean haveNotifiedLowMemory = false;
- OSErr err = noErr;
- long sleep;
- TWindowKind kind;
-
- cursorRgn = NewRgn();
-
- while (!gDone) {
-
- wind = MyFrontWindow();
- if (GetMyWindowKind(wind) == kStatus) DoClose(wind);
-
- if (gLongOperation && gInBackground) NotifyUser();
-
- memOK = RecoverReserveMemory();
- if (memOK) {
- haveNotifiedLowMemory = false;
- } else if (!haveNotifiedLowMemory) {
- CautionMessageNumber(kStrMemoryLow);
- haveNotifiedLowMemory = true;
- }
- EndCriticalMemorySequence(false);
-
- HandleIdle(cursorRgn);
-
- gCancel = gLongOperation = gInDialog = false;
- gDragPostProcessor = nil;
-
- if (gInBackground) {
- /* sleep = 0x7fffffff; - doesn't work: drag text to message
- wind while in background, window doesn't update! */
- sleep = GetCaretTime();
- rgn = nil;
- } else {
- kind = GetMyWindowKind(FrontWindow());
- if (kind == kGroup || kind == kSubject) {
- /*sleep = 0x7fffffff;*/
- sleep = GetCaretTime();
- rgn = nil;
- } else {
- sleep = GetCaretTime();
- rgn = cursorRgn;
- }
- }
-
- gotEvt = WaitNextEvent(everyEvent, &ev, sleep, rgn);
-
- if (gotEvt) {
- gPrevEvent = gCurEvent;
- gCurEvent = ev;
- HandleEvent(&ev);
- }
-
- if (gDragErr != noErr) {
- ReportSystemError(gDragErr);
- gDragErr = noErr;
- }
-
- if (gDragPostProcessor != nil) {
- err = (*gDragPostProcessor)();
- ReportSystemError(err);
- }
-
- if (gDone) gDone = Quit();
-
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- GiveTime
-
- Give time to other processes during long operations. Check for
- user cancels. Spin the beachball cursor.
-
- Entry: waiting = true if waiting for net driver or something else -
- yield CPU continuously to other processes while
- waiting.
- waiting = false if busy doing some kind of computation -
- yield CPU to other processes only once every 5 ticks.
-
- Exit: function result = error code (userCanceledErr if canceled
- by user, else noErr).
- ----------------------------------------------------------------------------*/
-
- OSErr GiveTime (Boolean waiting)
- {
- EventRecord ev;
- Boolean gotEvt;
- Point where;
- WindowPtr wind;
- TWindowKind kind;
- GrafPtr port;
- static long nextTime = 0;
- static DialogPtr waitForDNRDlg;
-
- if (!gLongOperation) {
- HiliteMenu(0);
- SpinCursor(0);
- ShowCursor();
- gLongOperation = true;
- }
-
- if (TickCount() >= nextTime) {
- #ifdef powerc
- SpinCursor(32); /* joke - spin cursor twice as fast on Power Macs */
- #else
- SpinCursor(16);
- #endif
- nextTime = TickCount() + 5;
- waiting = true;
- }
-
- if (waiting) {
- gotEvt = WaitNextEvent(everyEvent & ~highLevelEventMask & ~diskMask,
- &ev, 0, nil);
- if (gotEvt) HandleEvent(&ev);
- }
-
- if (gCancel && waitForDNRDlg == nil && NetMacTCPDNROperationInProgress()) {
- MyGetNewDialog(kWaitForDNRDlg, 0, 0, &waitForDNRDlg);
- if (waitForDNRDlg != nil) {
- RestoreMovableModalDialogPosition(waitForDNRDlg, gPrefs.waitForDNRLoc);
- MyShowWindow(waitForDNRDlg);
- }
- }
-
- if (waitForDNRDlg != nil && !NetMacTCPDNROperationInProgress()) {
- SaveMovableModalDialogPosition(waitForDNRDlg, &gPrefs.waitForDNRLoc);
- DoClose(waitForDNRDlg);
- waitForDNRDlg = nil;
- }
-
- if (!gInBackground && HMGetBalloons() && !HMIsBalloon()) {
- wind = FrontWindow();
- kind = GetMyWindowKind(wind);
- if (kind != kNotOurWind) {
- GetPort(&port);
- SetPort(wind);
- GetMouse(&where);
- if (PtInRect(where, &wind->portRect)) (*gDispatch[kind].help)(wind, where);
- SetPort(port);
- }
- }
-
- AdjustMenuHelpBalloons(false);
- AdjustHelpMenu();
-
- return gCancel ? userCanceledErr : noErr;
- }
-
- static OSErr GiveTimeDuringNetworkOperation (void)
- {
- #ifdef testingOT
- long xxx;
- Delay(OTDelay, &xxx);
- #endif
-
- return GiveTime(true);
- }
-
- static OSErr GiveTimeDuringCPUOperation (void)
- {
- return GiveTime(false);
- }
-
-
-
- /*----------------------------------------------------------------------------
- ForceCodeHigh
-
- Load all unloaded CODE resources, force them to high memory,
- and lock them.
-
- Does nothing in Power PC mode.
- ----------------------------------------------------------------------------*/
-
- static void ForceCodeHigh (void)
- {
- Handle h;
- short refNum, curRefNum, i, rID;
- ResType rType;
- Str255 rName;
- OSErr err = noErr;
-
- #ifdef powerc
- return;
- #endif
-
- h = GetResource('CODE', 1);
- if (h == nil) return;
- refNum = HomeResFile(h);
- curRefNum = CurResFile();
- UseResFile(refNum);
- SetResLoad(false);
- for (i = 1; ; i++) {
- h = Get1IndResource('CODE', i);
- if (h == nil) break;
- GetResInfo(h, &rID, &rType, rName);
- if (rID != 0) {
- LoadResource(h);
- HLockHi(h);
- }
- }
- SetResLoad(true);
- UseResFile(curRefNum);
-
- /* Force segment loader to know that ANSI seg is loaded. */
-
- strlen("");
- }
-
-
-
- /*----------------------------------------------------------------------------
- Init
-
- Initialize the program.
-
- Exit: function result = true if startup OK up through establishing a
- connection with the news server and getting the full
- group list (either from the prefs file or from the
- server), false otherwise.
- ----------------------------------------------------------------------------*/
-
- static Boolean Init (void)
- {
- EventRecord ev;
- AppleEvent firstEvent = {0, nil};
- AppleEvent firstReply = {0, nil};
- CStr255 msg;
- Boolean mightHaveNewGroups = true;
- short sizeofTPrefRec;
- long systemVersion, dragMgrAttr;
- OSErr err = noErr;
- Boolean savedNoNewConnection;
- Handle mbar;
- CStr255 fmt;
- ProcessSerialNumber myPSN, frontPSN;
- Boolean inFront;
- TGroup **newGroupsArray = nil;
- short numNewGroups = 0;
- WindowPtr wind;
- Handle h;
- DialogPtr dlg;
- short item;
-
- /* Initialize the toolbox. */
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- /* Allocate a 1K memory block, force it to the top of the heap, and lock it.
- This block is not used for anything - it is put at the top of the heap
- as a sacrifice because sometimes MacSLIP's VBL task trashes the end of
- the heap. Note: This problem was fixed in MacSLIP 2.0.6. */
-
- h = NewHandle(1000);
- if (h != nil) {
- MoveHHi(h);
- HLock(h);
- }
-
- /* Check for System 7.0 or later. */
-
- if (!MyTrapAvailable(_Gestalt)) {
- StopAlert(kNeedSystem7AlertID, nil);
- ExitToShell();
- }
- err = Gestalt(gestaltSystemVersion, &systemVersion);
- if (err != noErr || systemVersion < 0x0700) {
- StopAlert(kNeedSystem7AlertID, nil);
- ExitToShell();
- }
-
- /* In 68k mode, preload and force all CODE resources to locked high memory.
- This strategy is used instead of unloadseg calls to avoid fragmenting
- the heap. */
-
- ForceCodeHigh();
-
- /* Intialize the memory utilities. */
-
- InitMemUtil(40000, 40000);
-
- /* Initialize the window handling module method dispatch tables. */
-
- InitGroupDispatchTable();
- InitSubjectDispatchTable();
- InitArticleDispatchTable();
- InitMessageDispatchTable();
- InitTextDispatchTable();
- InitHelpDispatchTable();
- InitStatusDispatchTable();
- InitDialogDispatchTable();
- InitDummyDispatchTable();
-
- /* Intialize miscellaneous UPPs. */
-
- sfutil_InitUPP();
- print_InitUPP();
- prefsdlog_InitUPP();
- ldef_InitUPP();
-
- /* Create a pool of 50 window records in locked high memory, again to
- avoid later heap fragmentation. */
-
- err = InitializeWindowRecordStorage(50);
- if (err != noErr) goto exit1;
-
- /* Initialize the spinning beachball cursor. */
-
- InitCursorCtl(nil);
-
- /* Flush the event queue. */
-
- FlushEvents(everyEvent,0);
- EventAvail(everyEvent, &ev);
-
- /* Check for Drag Manager 1.1 or later and TextEdit outline hilite feature. */
-
- err = Gestalt(gestaltDragMgrAttr, &dragMgrAttr);
- gHaveDragMgr = err == noErr && (dragMgrAttr & (1L << gestaltDragMgrPresent)) != 0
- && (dragMgrAttr & (1L << gestaltDragMgrFloatingWind)) != 0;
- #ifdef powerc
- gHaveDragMgr = gHaveDragMgr &&
- (dragMgrAttr & (1L << gestaltPPCDragLibPresent)) != 0
- && (long)InstallTrackingHandler != kUnresolvedSymbolAddress;
- #endif
- gHaveTEOutlineHilite = HaveTEOutlineHiliteFeature();
-
- /* Get the desktop extent and ibeam and watch cursors. Initialize SpinCursor. */
-
- gDesktopExtent = (**GetGrayRgn()).rgnBBox;
- gIBeamCurs = **(GetCursor(iBeamCursor));
- gWatchCurs = **(GetCursor(watchCursor));
- SpinCursor(0);
-
- /* Create and draw the menu bar. */
-
- mbar = GetNewMBar(kMBarID);
- SetMenuBar(mbar);
- AppendResMenu(GetMenuHandle(kAppleMenu), 'DRVR');
- DrawMenuBar();
- InitHelpMenu();
-
- /* Figure out whether we were launched in the background or foreground. */
-
- GetCurrentProcess(&myPSN);
- GetFrontProcess(&frontPSN);
- SameProcess(&myPSN, &frontPSN, &inFront);
- gInBackground = !inFront;
-
- /* Check to see if we screwed up the size of the prefs struct. This is
- for sanity testing during development. */
-
- sizeofTPrefRec = sizeof(TPrefRec);
- if (sizeofTPrefRec != kTPrefRecSize) {
- GetCString(kStrSizeofTPrefRecBadFmt, fmt);
- sprintf(msg, fmt, sizeofTPrefRec, kTPrefRecSize);
- ErrorMessage(msg);
- ExitToShell();
- }
-
- /* Initialize Apple event handling. */
-
- err = InitializeAppleEvents(&firstEvent, &firstReply);
- if (err != noErr) goto exit1;
-
- /* Read the preferences file */
-
- err = ReadPrefs(&firstEvent);
- savedNoNewConnection = gPrefs.noNewConnection;
- if (err != noErr) goto exit1;
-
- /* Open the log file. */
-
- if (gPrefs.logActionsToFile) OpenLogFile();
-
- /* Open network driver (MacTCP or Open Transport). */
-
- err = DisplayStatusMessageNumber(NetHaveOT() ? kStrOpeningOTStatusMsg :
- kStrOpeningMacTCPStatusMsg);
- if (err != noErr) goto exit1;
-
- err = NetInit(GiveTimeDuringNetworkOperation, Log, 2);
- if (err != noErr) goto exit1;
-
- #ifdef testingOT
- TestOT();
- #endif
-
- /* Initialize the nntp.c module. */
-
- NntpInit(GiveTimeDuringCPUOperation);
-
- /* Open the initial connection to the news server. */
-
- gPrefs.noNewConnection = true;
- while (true) {
- err = StartNNTP();
- if (err == noErr) break;
- ReportSystemError(err);
- err = MyGetNewDialog(kRetryConnectID, ok, cancel, &dlg);
- if (err != noErr) goto exit1;
- RestoreMovableModalDialogPosition(dlg, gPrefs.retryConnectLoc);
- MyMovableModalDialog(dlg, DialogFilter, &item);
- SaveMovableModalDialogPosition(dlg, &gPrefs.retryConnectLoc);
- err = DoClose(dlg);
- if (err != noErr) goto exit1;
- if (item == cancel) goto exit1;
- }
-
- /* Get the full group list from the server if necessary. */
-
- if (gNumGroups == 0) {
- err = DoRebuildFullGroupList();
- if (err != noErr) goto exit1;
- mightHaveNewGroups = false;
- }
-
- /* Create the full group window. */
-
- err = MakeFullGroupWindow(gFullGroupArray, gNumGroups, &gFullGroupWindow);
- if (err != noErr) goto exit1;
-
- /* Check for new groups if necessary and requested by the user. */
-
- if (mightHaveNewGroups && gPrefs.checkForNewGroups) {
- err = CheckForNewGroups(&newGroupsArray, &numNewGroups);
- if (err != noErr && err != userCanceledErr) goto exit2;
- gCancel = false;
- }
-
- /* Auto-fetch a newsrc file from a remote host if requested by the user. */
-
- if (gPrefs.autoFetchNewsrc) {
- err = AutoFetchNewsrcFromHost();
- if (err != noErr && err != userCanceledErr) goto exit2;
- gCancel = false;
- }
-
- /* Handle the initial Apple event. */
-
- MyAEResumeTheCurrentEvent(&firstEvent, &firstReply,
- (AEEventHandlerUPP)kAEUseStandardDispatch, 0);
- firstEvent.dataHandle = nil;
-
- /* If there are new groups, create the new groups window. */
-
- if (numNewGroups > 0) {
- err = MakeNewGroupsWindow(newGroupsArray, numNewGroups, &wind);
- if (err != noErr) goto exit2;
- }
-
- gPrefs.noNewConnection = savedNoNewConnection;
- ResetNewsServerOptions();
-
- return true;
-
- exit1:
-
- if (firstEvent.dataHandle != nil)
- MyAEResumeTheCurrentEvent(&firstEvent, &firstReply,
- (AEEventHandlerUPP)kAENoDispatch, 0);
- EndNNTP();
- ReportSystemError(err);
- ErrorMessageNumber(kStrStartupError);
- gPrefs.noNewConnection = savedNoNewConnection;
- return false;
-
- exit2:
-
- if (firstEvent.dataHandle != nil)
- MyAEResumeTheCurrentEvent(&firstEvent, &firstReply,
- (AEEventHandlerUPP)kAENoDispatch, 0);
- ReportSystemError(err);
- gPrefs.noNewConnection = savedNoNewConnection;
- ResetNewsServerOptions();
- return true;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Term
-
- Terminate the program.
- ----------------------------------------------------------------------------*/
-
- static void Term (void)
- {
- OSErr err = noErr;
-
- err = WritePrefs();
- ReportSystemError(err);
- DeleteTemporaryFiles(kNewsWatcherSignature);
- EndNNTP();
- NetTerm();
- if (gPrefs.logActionsToFile) CloseLogFile();
- MyICStop();
- AdjustMenuHelpBalloons(true);
- }
-
-
- /*----------------------------------------------------------------------------
- main
-
- Main entry point.
- ----------------------------------------------------------------------------*/
-
- void main (void)
- {
- short i;
-
- SetApplLimit(GetApplLimit() - 20000);
- MaxApplZone();
- for (i = 0; i < 20; i++) MoreMasters();
- gStartupOK = Init();
- gStartingUp = false;
- MainEvent();
- Term();
- }
-